﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using CommonLib;
using Newtonsoft.Json;
using System.IO;
using System;
using System.Text;

public class LevelEditorWindow : EditorWindow
{
	[MenuItem("Assets/Editor/BattleLevelFile")]
	static public void OpenEditorWindow()
	{
		LevelEditorWindow window = EditorWindow.GetWindow<LevelEditorWindow>();
		window.WindowInit();
		window.Show();

	}


	private void OnGUI()
	{
		EditorGUILayout.BeginVertical();
		#region 编辑配置信息
		EditorGUI.BeginDisabledGroup(true);
		EditorGUILayout.ObjectField("Current File",EditorAsset, typeof(TextAsset), false);
		//EditorGUILayout.LabelField("EditorFile", EditorFile);
		EditorGUILayout.LabelField("SelectPath", SelectPath);
		EditorGUI.EndDisabledGroup();
		#endregion
		#region 内容配置信息
		ScrollPosition = EditorGUILayout.BeginScrollView(ScrollPosition);

		//Title
		
		//foreach(var bl in Levels)
		for (int index = 0; index < Levels.Count; index++)
		{
			//EditorGUILayout.SelectableLabel(bl.Name, new GUIStyle("BoldLabel"), GUILayout.Width(100));
			var bl = Levels[index];
			GUI.SetNextControlName(index.ToString());

			EditorGUILayout.SelectableLabel(bl.Name, GUILayout.Height(18), GUILayout.Width(100));
			//Level Infor
			bl.Name = EditorGUILayout.TextField("Level Name :", bl.Name);
			bl.Level = EditorGUILayout.IntField("Level Index :", bl.Level);
			//Map Infor
			bl.MapWidth = EditorGUILayout.FloatField("Map Width :", bl.MapWidth);
			bl.MapHeight = EditorGUILayout.FloatField("Map Height :", bl.MapHeight);
			bl.MinSize = EditorGUILayout.FloatField("Map Celling Mini Size :", bl.MinSize);
			//Other Infor

			//for (int index = 0; index < bl.LstTrigger.Count; index++)
			//{
			//	var trigger = bl.LstTrigger[index];
			//	var set = bl.lstInstructionSet[index];
			//
			//}
			if (GUILayout.Button("EditTrigger"))
			{
				LevelInstructionEditorWindow win = EditorWindow.GetWindow<LevelInstructionEditorWindow>(bl.Name);
				//win.ShowModalUtility();
				//win.ShowUtility();
				win.WindowInit(index, this);
			}
			

			EditorGUILayout.Space();
		}
		EditorGUILayout.EndScrollView();
		#endregion

		#region Button
		EditorGUILayout.BeginHorizontal();
		GUILayout.FlexibleSpace();
		if (GUILayout.Button("Add Level", GUILayout.Width(100)))
		{
			AddLevel();
		}
		if (GUILayout.Button("Delete Level", GUILayout.Width(100)))
		{
			int index = int.Parse(GUI.GetNameOfFocusedControl());
			Levels.RemoveAt(index);
		}
		EditorGUILayout.EndHorizontal();
		if (GUILayout.Button("Save"))
		{
			Save();
		}
		#endregion
		EditorGUILayout.EndVertical();
	}

	protected void WindowInit()
	{
		TextAsset jsonFile = EditorUtil.GetSelectT<TextAsset>();

		Levels = new List<BattleLevelEntity>();
		if(null != jsonFile)
			Levels.AddRange(JsonConvert.DeserializeObject<List<BattleLevelEntity>>(jsonFile.text));
		if (Levels.Count != 0)
		{
			EditorFile = jsonFile.text;
			EditorAsset = jsonFile;
			this.SelectPath = AssetDatabase.GetAssetPath(jsonFile);
		}
		//this.SelectPath = EditorUtil.GetSelectFolder();
		else
		{
			EditorFile = null;
			EditorAsset = null;
			this.SelectPath = EditorUtil.GetSelectFolder();
		}
	}

	protected void Save()
	{
		if (Levels.Count <= 0)
			return;
		string path;
		if (null == this.EditorAsset) {
			path = EditorUtility.SaveFilePanel("Save Path", SelectPath, "BattleLevelFile", "txt");
		}
		else
		{
			path = this.SelectPath;
		}
		if(!string.IsNullOrEmpty(path))
		{
			using (BinaryWriter bw = new BinaryWriter(new FileStream(path, FileMode.Create, FileAccess.Write)))
			{
				try
				{
					string tempString = JsonConvert.SerializeObject(Levels);
					byte[] byt = Encoding.UTF8.GetBytes(tempString);
					bw.Write(byt, 0 , byt.Length);
				}
				catch (Exception e)
				{
					Debug.LogError($"序列化信息异常 ：{e.StackTrace}");
				}
			}
			if(File.Exists(path))
				AssetDatabase.ImportAsset(path);
		}

	}

	protected void AddLevel()
	{
		Levels.Add(new BattleLevelEntity()
		{
			Level = Levels.Count,
			MapHeight = 1,
			MapWidth = 1,
			MinSize = 1,
			Name = "Temp",
			LstTrigger = new List<BPTrigger>(),
			LstInstructionSet = new List<BPInstructionSet>()
		});
	}

	#region Edit With Trigger And InstructionSet
	public void AddTriggerByLevelIndex(int index)
	{
		Levels[index].LstTrigger.Add(new BPTrigger());
		Levels[index].LstInstructionSet.Add(new BPInstructionSet());
	}

	public void RemoveTriggerByLevelIndex(int index, int itemIndex)
	{
		Levels[index].LstTrigger.RemoveAt(itemIndex);
		Levels[index].LstInstructionSet.RemoveAt(itemIndex);
	}

	public void SwitchTrigger(int index, int from, int to)
	{
		
		if( to >= 0 && to <= Levels[index].LstTrigger.Count - 1)
		{
			var tempT = Levels[index].LstTrigger[from];
			Levels[index].LstTrigger[from] = Levels[index].LstTrigger[to];
			Levels[index].LstTrigger[to] = tempT;

			var tempI = Levels[index].LstInstructionSet[from];
			Levels[index].LstInstructionSet[from] = Levels[index].LstInstructionSet[to];
			Levels[index].LstInstructionSet[to] = tempI;
		}
	}

	#endregion

	#region Edit Instruction
	public void AddInstruction(int levelIndex,int setIndex)
	{
		Levels[levelIndex].LstInstructionSet[setIndex].LstInstruction.Add(new BPInstruction());
	}

	public void RemoveInstruction(int levelIndex, int setIndex, int index)
	{
		Levels[levelIndex].LstInstructionSet[setIndex].LstInstruction.RemoveAt(index);
	}

	public void SwitchInstruction(int levelIndex, int setIndex, int from, int to)
	{
		var lstInstru = Levels[levelIndex].LstInstructionSet[setIndex].LstInstruction;
		if (to >= 0 && to <= lstInstru.Count - 1)
		{
			var temp = lstInstru[from];
			lstInstru[from] = lstInstru[to];
			lstInstru[to] = temp;
		}

	}
	#endregion

	public BattleLevelEntity GetLevelByIndex(int index)
	{
		return Levels[index];
	}
	
	protected TextAsset EditorAsset { get; set; }
	protected string EditorFile { get; set; }
	protected string SelectPath { get; set; }
	public List<BattleLevelEntity> Levels { get; set; }

	protected Vector2 ScrollPosition { get; set; } = Vector2.zero;
}

public class LevelInstructionEditorWindow : EditorWindow
{
	public void OnGUI()
	{
		//EditorGUILayout.LabelField("",new GUIStyle("toolbarbutton") { alignment = TextAnchor.MiddleCenter});
		EditorGUILayout.LabelField("Triggers", new GUIStyle("toolbarbutton") { alignment = TextAnchor.MiddleCenter });
		BattleLevelEntity level = this.Parent.GetLevelByIndex(this.Index);


		EditorGUILayout.BeginVertical();
		#region 编辑配置信息
		EditorGUI.BeginDisabledGroup(true);

		EditorGUI.EndDisabledGroup();
		#endregion
		#region 内容配置信息
		ScrollPosition = EditorGUILayout.BeginScrollView(ScrollPosition);

		for (int index = 0; index < level.LstTrigger.Count; index++)
		{
			EditorGUILayout.BeginHorizontal(new GUIStyle("Box"));

			EditorGUILayout.BeginVertical();
			var trigger = level.LstTrigger[index];
			GUI.SetNextControlName(index.ToString());
			trigger.TriggerName = EditorGUILayout.TextField("Name", trigger.TriggerName);
			trigger.BPTType = (BPTrigger.BPTriggerType)EditorGUILayout.EnumPopup("Type", trigger.BPTType);
			EditorGUILayout.LabelField("ParamString :");
			trigger.ParamString = EditorGUILayout.TextArea(trigger.ParamString, GUILayout.Height( EditorGUIUtility.singleLineHeight * 3));

			switch (trigger.BPTType)
			{
				case BPTrigger.BPTriggerType.SceneAbout :
					trigger.SceneEvent = (int)(SceneEvent)EditorGUILayout.EnumPopup("场景事件：", (SceneEvent)trigger.SceneEvent);
					trigger.Scene = (int)(Scene)EditorGUILayout.EnumPopup("场景：", (Scene)trigger.Scene);
					break;
				case BPTrigger.BPTriggerType.PlayerCountAbout:
					trigger.PlayerMinCount = EditorGUILayout.IntField("最小值 :", trigger.PlayerMinCount);
					trigger.PlayerMaxCount = EditorGUILayout.IntField("最大值 :", trigger.PlayerMaxCount);
					break;
			}

			if (GUILayout.Button("Edit Instruction"))
			{
				InstructEditorWindow window = EditorWindow.GetWindow<InstructEditorWindow>();
				window.WindowInit(index, this.Index, this.Parent);
			}
			EditorGUILayout.EndVertical();

			EditorGUILayout.BeginVertical();
			if (GUILayout.Button("Up"))
			{
				this.Parent.SwitchTrigger(this.Index, index, index - 1);
			}
			if (GUILayout.Button("Dw"))
			{
				this.Parent.SwitchTrigger(this.Index, index, index + 1);
			}
			if (GUILayout.Button("-"))
			{
				this.Parent.RemoveTriggerByLevelIndex(this.Index, index);
			}
			EditorGUILayout.EndVertical();
			EditorGUILayout.EndHorizontal();
		}

		EditorGUILayout.EndScrollView();
		#endregion

		#region Button
		EditorGUILayout.BeginHorizontal();
		GUILayout.FlexibleSpace();
		if (GUILayout.Button(" + ", GUILayout.Width(100)))
		{
			this.Parent.AddTriggerByLevelIndex(this.Index);
		}
		EditorGUILayout.EndHorizontal();
		#endregion
		EditorGUILayout.EndVertical();
	}


	public void WindowInit(int index, LevelEditorWindow parent)
	{
		this.Parent = parent;
		this.Index = index;
		

	}

	protected LevelEditorWindow Parent { get; set; }
	protected int Index { get; set; }
	protected Vector2 ScrollPosition { get; set; } = Vector2.zero;
}

public class InstructEditorWindow : EditorWindow
{
	private void OnGUI()
	{

		EditorGUILayout.LabelField("Instructions", new GUIStyle("toolbarbutton") { alignment = TextAnchor.MiddleCenter });
		BPInstructionSet Set = this.Parent.GetLevelByIndex(this.LevelIndex).LstInstructionSet[this.TriggerIndex];


		EditorGUILayout.BeginVertical();
		#region 编辑配置信息
		EditorGUI.BeginDisabledGroup(true);

		EditorGUI.EndDisabledGroup();
		#endregion
		#region 内容配置信息
		ScrollPosition = EditorGUILayout.BeginScrollView(ScrollPosition);

		for (int index = 0; index < Set.LstInstruction.Count; index++)
		{
			var instru = Set.LstInstruction[index];
			instru.Index = Set.LstInstruction.IndexOf(instru);
			EditorGUILayout.BeginHorizontal(new GUIStyle("Box"));

			EditorGUILayout.BeginVertical();
			//Type
			instru.InstructType = (BPInstruction.InstructionType)EditorGUILayout.EnumPopup("指令类型 :",instru.InstructType);
			
			//Content
		
			switch (instru.InstructType)
			{
				
				case BPInstruction.InstructionType.Wait:
					if (null == instru.Params[0])
						instru.Params[0] = 0.ToString();
					instru.Params[0] = EditorGUILayout.FloatField("等待时间 :", float.Parse(instru.Params[0])).ToString();
					break;
				case BPInstruction.InstructionType.SendSceneEvent:
					if (null == instru.Params[0])
						instru.Params[0] = 0.ToString();
					if (null == instru.Params[1])
						instru.Params[1] = 0.ToString();
					instru.Params[0] = ((int)(SceneEvent)EditorGUILayout.EnumPopup("场景事件：", (SceneEvent) int.Parse(instru.Params[0]))).ToString();
					instru.Params[1] = ((int)(Scene)EditorGUILayout.EnumPopup("场景：", (Scene)int.Parse(instru.Params[1]))).ToString();
					break;
				//case BPInstruction.InstructionType.Kill_Instruction:
				//	if (null == instru.Params[0])
				//		instru.Params[0] = 0.ToString();
				//	instru.Params[0] = EditorGUILayout.IntField("指令Index :", int.Parse(instru.Params[0])).ToString();
				//	break;
				case BPInstruction.InstructionType.Open_Trigger:
				case BPInstruction.InstructionType.Kill_Trigger:
					instru.Params[0] = EditorGUILayout.TextField("TriggerName :", instru.Params[0]);
					break;

				case BPInstruction.InstructionType.Create_Npc:
				case BPInstruction.InstructionType.Create_Player:
					instru.Params[0] = EditorGUILayout.TextField("Tag :", instru.Params[0]);
					break;
				case BPInstruction.InstructionType.Create_EffectItem:
					if (null == instru.Params[0])
						instru.Params[0] = 0.ToString();	
				    EffectItemFactory.EffectItemType etype =
						(EffectItemFactory.EffectItemType)EditorGUILayout.EnumPopup("类型 :",(EffectItemFactory.EffectItemType)int.Parse(instru.Params[0]));
					instru.Params[0] = ((int)etype).ToString();
					if (null == instru.Params[1])
						instru.Params[1] = 0.ToString();
					instru.Params[1] = EditorGUILayout.IntField("间隔时间 :", int.Parse(instru.Params[1])).ToString();

					if (null == instru.Params[2])
						instru.Params[2] = 0.ToString();
					if (null == instru.Params[3])
						instru.Params[3] = 0.ToString();
					switch (etype)
					{
						case EffectItemFactory.EffectItemType.Plus:
						case EffectItemFactory.EffectItemType.Minus:
							instru.Params[2] = EditorGUILayout.FloatField("Effect Score :", float.Parse(instru.Params[2])).ToString();
							instru.Params[3] = EditorGUILayout.TextField("Apply Image :", instru.Params[3]);
							break;
						case EffectItemFactory.EffectItemType.Speed:
							instru.Params[2] = EditorGUILayout.FloatField("Effect Speed :", float.Parse(instru.Params[2])).ToString();
							instru.Params[3] = EditorGUILayout.FloatField("Effect Duration :", float.Parse(instru.Params[3])).ToString();
							break;
						case EffectItemFactory.EffectItemType.SpeedMulti:
							instru.Params[2] = EditorGUILayout.FloatField("Effect Speed Multi :", float.Parse(instru.Params[2])).ToString();
							instru.Params[3] = EditorGUILayout.FloatField("Effect Duration :", float.Parse(instru.Params[3])).ToString();
							break;
					}
					break;

				case BPInstruction.InstructionType.AttachAI:
					instru.Params[0] = EditorGUILayout.TextField("Tag :", instru.Params[0]);
					break;
				case BPInstruction.InstructionType.None:
					break;
			}
			

			EditorGUILayout.EndVertical();
			EditorGUILayout.BeginVertical();
			if (GUILayout.Button("Up"))
			{
				this.Parent.SwitchInstruction(this.LevelIndex, this.TriggerIndex, index, index - 1);
			}
			if (GUILayout.Button("Dw"))
			{
				this.Parent.SwitchInstruction(this.LevelIndex, this.TriggerIndex, index, index + 1);
			}
			if (GUILayout.Button("-"))
			{
				this.Parent.RemoveInstruction(this.LevelIndex, this.TriggerIndex, index);
			}
			EditorGUILayout.EndVertical();

			EditorGUILayout.EndHorizontal();
		}

		EditorGUILayout.EndScrollView();
		#endregion

		#region Button
		EditorGUILayout.BeginHorizontal();
		GUILayout.FlexibleSpace();
		if (GUILayout.Button(" + ", GUILayout.Width(100)))
		{
			this.Parent.AddInstruction(this.LevelIndex, this.TriggerIndex);
		}

		EditorGUILayout.EndHorizontal();
		#endregion
		EditorGUILayout.EndVertical();
	}

	public void WindowInit(int triggerIndex, int levelIndex, LevelEditorWindow parent)
	{
		this.Parent = parent;
		this.TriggerIndex = triggerIndex;
		this.LevelIndex = levelIndex;
	}
	protected int TriggerIndex { get; set; }
	protected int LevelIndex { get; set; }
	protected LevelEditorWindow Parent {get; set;}

	protected Vector2 ScrollPosition { get; set; } = Vector2.zero;
}